#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from typing import List, Dict, Optional, Tuple

from filters import FilterRule
from filters.filter_stats import FilterStats
from .change_type_detector import ChangeTypeDetector

class UnitSplitter:
    """单元分割器，负责将复杂diff拆分成多个单位"""
    
    def __init__(self, filter_rules: Optional[List[FilterRule]] = None, enable_stats: bool = True):
        """初始化分割器"""
        if filter_rules is None:
            filter_rules = []
        self.filter_rules = filter_rules
        self.enable_stats = enable_stats
        self.filter_stats = FilterStats() if enable_stats else None
    
    def add_filter_rule(self, rule: FilterRule) -> None:
        """添加过滤规则"""
        self.filter_rules.append(rule)
    
    def get_filter_stats(self) -> Dict[str, int]:
        """获取筛选统计"""
        if self.filter_stats:
            return self.filter_stats.get_stats()
        return {}
    
    def get_detailed_filter_stats(self) -> Dict[str, List]:
        """获取详细筛选统计"""
        if self.filter_stats:
            return self.filter_stats.get_detailed_stats()
        return {}
    
    def print_filter_stats(self):
        """打印筛选统计"""
        if self.filter_stats:
            self.filter_stats.print_summary()
        else:
            print("筛选统计未启用")
    
    def reset_filter_stats(self):
        """重置筛选统计"""
        if self.filter_stats:
            self.filter_stats.reset()
    
    def extract_change_pairs(self, hunk_changes: List[Dict]) -> List[tuple]:
        """提取实际的添加和删除内容"""
        return ChangeTypeDetector.extract_change_pairs(hunk_changes=hunk_changes)
    
    def determine_change_type(self, add_content: str, remove_content: str) -> str:
        """确定修改类型"""
        return ChangeTypeDetector.determine_change_type(add_content, remove_content)
    
    def is_meaningful_change(self, add_content: str, remove_content: str, hunk_changes: List[Dict], file_path: str = None) -> tuple:
        """判断是否为有意义的修改，返回(是否保留, 筛选原因)"""
        # 使用策略模式，遍历所有过滤规则
        for rule in self.filter_rules:
            if hasattr(rule, 'get_rule_name') and 'FileExtension' in rule.get_rule_name():
                filter_data = [{'file_path': file_path}] if file_path else hunk_changes
                if rule.should_filter(add_content, remove_content, filter_data):
                    if self.enable_stats and self.filter_stats:
                        filter_name = rule.get_rule_name()
                        filter_reason = rule.get_filter_reason()
                        unit_info = {
                            'add_content': add_content,
                            'remove_content': remove_content,
                            'file_path': file_path
                        }
                        self.filter_stats.record_filter(filter_name, filter_reason, unit_info)
                    return False, f"filtered_by_{rule.get_rule_name()}"
            else:
                if rule.should_filter(add_content, remove_content, hunk_changes):
                    if self.enable_stats and self.filter_stats:
                        filter_name = rule.get_rule_name()
                        filter_reason = rule.get_filter_reason()
                        unit_info = {
                            'add_content': add_content,
                            'remove_content': remove_content,
                            'file_path': file_path
                        }
                        self.filter_stats.record_filter(filter_name, filter_reason, unit_info)
                    return False, f"filtered_by_{rule.get_rule_name()}"
        
        return True, None
    
    def split_hunk_into_units(self, pr_number: int, file_path: str, hunk: Dict, global_unit_counter: int = 0) -> Tuple[List[Dict], List[Dict], int]:
        """将单个hunk拆分成多个units，返回(有效units, 被筛除units, 更新后的全局计数器)的元组"""
        valid_units = []
        rejected_units = []
        hunk_changes = hunk['changes']
        
        change_pairs = self.extract_change_pairs(hunk_changes)
        
        for i, (add_content, remove_content, context_before, context_after) in enumerate(change_pairs):
            unit_id = f"PR{pr_number}_{file_path.replace('/', '_')}_unit_{global_unit_counter}"
            global_unit_counter += 1
            
            unit = {
                'pr_number': pr_number,
                'file_path': file_path,
                'hunk_header': hunk['hunk_header'],
                'add_content': add_content,
                'remove_content': remove_content,
                'unit_id': unit_id,
                'context_before': context_before,
                'context_after': context_after
            }
            
            is_meaningful, filter_reason = self.is_meaningful_change(add_content, remove_content, hunk_changes, file_path)
            if not is_meaningful:
                unit['reason'] = filter_reason
                rejected_units.append(unit)
                continue
            
            change_type = self.determine_change_type(add_content, remove_content)
            
            if change_type == 'unknown':
                unit['reason'] = 'unknown_change_type'
                rejected_units.append(unit)
                continue
            
            unit['change_type'] = change_type
            valid_units.append(unit)
        
        return valid_units, rejected_units, global_unit_counter
    
    def split_pr_into_units(self, pr_data: Dict) -> Tuple[List[Dict], List[Dict]]:
        """将PR数据拆分成多个units，返回(有效units, 被筛除units)的元组"""
        valid_units = []
        rejected_units = []
        pr_number = pr_data['pr_info']['number']
        global_unit_counter = 0  # 全局unit计数器
        
        for diff in pr_data.get('diffs', []):
            file_path = diff['file']
            
            hunk = {
                'hunk_header': diff['hunk_header'],
                'changes': diff['changes']
            }
            
            hunk_valid_units, hunk_rejected_units, global_unit_counter = self.split_hunk_into_units(
                pr_number, file_path, hunk, global_unit_counter
            )
            valid_units.extend(hunk_valid_units)
            rejected_units.extend(hunk_rejected_units)
        
        return valid_units, rejected_units